package v1

import (
	"github.com/gin-gonic/gin"
	"manager/bll"
	"manager/errors"
	"manager/lib/infra"
	"manager/model"
	"manager/server/web/middleware"
	"manager/utils"
	"sort"
)

var Store = &store{}

func init() {
	// 注册路由
	RegisterRouter(Store)
}

type store struct{}

func (a *store) Init(r *gin.RouterGroup) {
	g := r.Group("/store", middleware.Auth())
	{
		g.POST("/create", a.create)
		g.POST("/update", a.update)
		g.POST("/list", a.list)
		g.POST("/delete", a.delete)
		g.POST("/info", a.info)                        //门店详情
		g.POST("/update_store_status", a.updateStatus) //门店上下线
	}

	appG := r.Group("app/store", middleware.Auth())
	{
		appG.POST("/nearby_stores", a.nearbyStores) //附近门店
	}
}

func (a *store) create(c *gin.Context) {
	var (
		in  = &model.StoreCreateRequest{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	if in.AreaID == 0 {
		c.Error(errors.New("请选择区域"))
		return
	}

	if err = bll.StoreServer.Create(c.Request.Context(), in); err != nil {
		c.Error(err)
		return
	}
	utils.ResponseOk(c, nil)
}

func (a *store) update(c *gin.Context) {
	var (
		in  = &model.StoreUpdateRequest{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	if err = bll.StoreServer.Update(c.Request.Context(), in); err != nil {
		c.Error(err)
		return
	}
	utils.ResponseOk(c, nil)
}

func (a *store) list(c *gin.Context) {
	var (
		in  = &model.StoreListRequest{}
		out = &model.StoreListResponse{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	if out, err = bll.StoreServer.List(c.Request.Context(), in); err != nil {
		c.Error(err)
		return
	}
	utils.ResponseOk(c, out)
}

func (a *store) delete(c *gin.Context) {
	var (
		in  = &model.StoreDeleteRequest{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	if err = bll.StoreServer.Delete(c.Request.Context(), in); err != nil {
		c.Error(err)
		return
	}
	utils.ResponseOk(c, nil)
}

func (a *store) info(c *gin.Context) {
	var (
		in  = &model.StoreBaseRequest{}
		out = &model.StoreInfo{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	if out, err = bll.StoreServer.FindByID(c.Request.Context(), in); err != nil {
		c.Error(err)
		return
	}
	utils.ResponseOk(c, out)
}

func (a *store) updateStatus(c *gin.Context) {
	var (
		in  = &model.StoreUpdateStatusRequest{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	if err = bll.StoreServer.UpdateStatus(c.Request.Context(), in); err != nil {
		c.Error(err)
		return
	}

	utils.ResponseOk(c, nil)
}

// nearbyStores 附近门店
func (a *store) nearbyStores(c *gin.Context) {
	var (
		in  = &model.NearbyStoresRequest{}
		out = &model.NearbyStoresResponse{}
		err error
	)

	if err = c.ShouldBindJSON(in); err != nil {
		c.Error(err)
		return
	}

	// 附近门店
	storeList, err := bll.StoreServer.List(c.Request.Context(), &model.StoreListRequest{
		Index: 1,
		Size:  -1,
	})
	if err != nil {
		c.Error(err)
		return
	}

	type storeDistance struct {
		StoreID  int64   `json:"store_id"`
		Distance float64 `json:"distance"`
	}

	// 计算距离
	storeInfoMap := make(map[int64]*model.StoreInfo, 0)
	var list []*storeDistance
	for i := 0; i < len(storeList.Data); i++ {
		storeInfoMap[storeList.Data[i].ID] = storeList.Data[i]
		distance := infra.Lbs.GeoDistance(in.Coordinate.X, in.Coordinate.Y, storeList.Data[i].Coordinate.X, storeList.Data[i].Coordinate.Y, "K")
		list = append(list, &storeDistance{
			StoreID:  storeList.Data[i].ID,
			Distance: distance,
		})
	}

	// 计算排序
	sort.Slice(list, func(i, j int) bool {
		return list[i].Distance < list[j].Distance
	})

	// 返回数据
	out.Data = make([]*model.NearbyStoreInfo, 0)
	for i := 0; i < len(list); i++ {
		if i >= 10 {
			continue
		}

		if _, ok := storeInfoMap[list[i].StoreID]; !ok {
			continue
		}

		out.Data = append(out.Data, &model.NearbyStoreInfo{
			StoreInfo: *storeInfoMap[list[i].StoreID],
			Distance:  int32(list[i].Distance),
		})
	}

	utils.ResponseOk(c, out)
}
